﻿using DrawControl.UI.Common;
using DrawControl.UI.Common.DrawControCenter;
using DrawControl.UI.Common.DrawControCenter.DrawSeal;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DrawControl.UI.View
{
    public partial class FrmImage : Form
    {
        private readonly Bitmap _bitmap;
        private readonly string _fileImage;
        public FrmImage(string fileImage)
        {
            _fileImage = fileImage;
            _bitmap = new Bitmap(_fileImage);

            InitializeComponent();
            SetStyle(
          ControlStyles.ResizeRedraw
          | ControlStyles.DoubleBuffer
          | ControlStyles.UserPaint
          | ControlStyles.AllPaintingInWmPaint
          | ControlStyles.SupportsTransparentBackColor,
          true
          );

            this.AllowDrop = true;
            this.DragEnter += FrmDragEnter;
            this.DragDrop += FrmDragDrop;
        }
        private float _scaleX;
        private float _scaleY;
        private float _scale;
        private int _x;
        private int _y;
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            int destWidth = this.Width;
            int destHeight = this.Height;
            int srcWidth = _bitmap.Width;
            int srcHeight = _bitmap.Height;
            _scaleX = destWidth / (float)srcWidth;
            _scaleY = destHeight / (float)srcHeight;
            _scale = Math.Min(_scaleX, _scaleY);
            int width = (int)(srcWidth * _scale);
            int height = (int)(srcHeight * _scale);
            _x = (destWidth - width) >> 1;
            _y = (destHeight - height) >> 1;

            BufferedGraphicsContext GraphicsContext = BufferedGraphicsManager.Current;
            using BufferedGraphics myBuffer = GraphicsContext.Allocate(e.Graphics, e.ClipRectangle);
            using Graphics g = myBuffer.Graphics;
            g.Clear(Color.White);
            g.DrawImage(_bitmap, _x, _y, width, height);
            myBuffer.Render(e.Graphics);
        }
        private const int defaultWidth = 603;
        private const int defaultHeight = 519;
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            this.Invalidate();

            float scaleX = defaultWidth / (float)this.Width;
            float scaleY = defaultHeight / (float)this.Height;
            float scale = Math.Min(scaleX, scaleY);
            foreach (Control control in this.Controls)
            {
                int adjustedX = (int)(control.Location.X / scaleX);
                int adjustedY = (int)(control.Location.Y / scaleY);
                //control.Size = new Size((int)(control.Width * scale), (int)(control.Height * scale));
                control.Location = new Point((int)(adjustedX), (int)(adjustedY));
            }
        }

        private void FrmDragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(ViewControl)))
            {
                e.Effect = DragDropEffects.Move | DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void FrmDragDrop(object sender, DragEventArgs e)
        {
            ViewControl vc = e.Data.GetData(typeof(ViewControl)) as ViewControl;
            Control control = null;
            if (vc.Seal == SealType.RectangleSeal)
            {
                RectangleSeal rectangleSeal = new RectangleSeal(128, 128);
                rectangleSeal.Padding = new Padding(5);
                rectangleSeal.BorderSize = 3;
                rectangleSeal.Text = "测试";
                rectangleSeal.RectangleSealType = 3;
                rectangleSeal.Draw();
                control = rectangleSeal;
                rectangleSeal.FormType=new FrmRectangleSealSetting();
                SettingFormCallback?.Invoke(rectangleSeal.FormType);
            }
            else
            {
                RingSeal ringSeal = new RingSeal(160, 160);
                ringSeal.Padding = new Padding(5);
                ringSeal.BorderSize = 3;
                ringSeal.Draw();
                control = ringSeal;
                ringSeal.FormType = new FrmRingSealSetting() ;
                SettingFormCallback?.Invoke(ringSeal.FormType);
            }
            Point screenPoint = Control.MousePosition;
            Point clientPoint = this.PointToClient(screenPoint);
            control.Location = new Point(clientPoint.X - (control.Width >> 1), clientPoint.Y - (control.Height >> 1));
            control.MouseMove += Seal_MouseMove;
            control.MouseUp += Seal_MouseUp;
            control.MouseDown += Seal_MouseDown;
            control.Cursor = Cursors.Hand;
            this.Controls.Add(control);
           
        }
        public Action<Form> SettingFormCallback;
        private Control _control;
        private Point lastMousePosition; // 记录鼠标按下时的屏幕坐标
        private void Seal_MouseDown(object? sender, MouseEventArgs e)
        {
            Point screenPoint = Control.MousePosition;
            Point clientPoint = this.PointToClient(screenPoint);
            foreach (Control control in this.Controls)
            {
                if (new Rectangle(control.Location, control.Size).Contains(clientPoint))
                {
                    _control = control;
                    SettingFormCallback?.Invoke((_control as IDrawControl).FormType);
                    break;
                }
            }

            lastMousePosition = clientPoint;
        }

        private void Seal_MouseUp(object? sender, MouseEventArgs e)
        {
            _control = null;
            this.Invalidate();
        }

        private void Seal_MouseMove(object? sender, MouseEventArgs e)
        {
            if (_control != null)
            {
                Point screenPoint = Control.MousePosition;
                Point currentMousePosition = this.PointToClient(screenPoint);
                int deltaX = currentMousePosition.X - lastMousePosition.X; // 计算X轴的偏移量
                int deltaY = currentMousePosition.Y - lastMousePosition.Y; // 计算Y轴的偏移量
                int x = _control.Location.X + deltaX;
                int y = _control.Location.Y + deltaY;
                x = x < 0 ? 0 : x;
                y = y < 0 ? 0 : y;
                x = x > this.Width - _control.Width ? this.Width - _control.Width : x;
                y = y > this.Height - _control.Height ? this.Height - _control.Height : y;
                _control.Location = new Point(x, y);

                lastMousePosition = currentMousePosition; 
            }
        }

        private void FrmImage_FormClosing(object sender, FormClosingEventArgs e)
        {
            _bitmap?.Dispose();
            this.Dispose();
        }
        /// <summary>
        /// 关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmiClose_Click(object sender, EventArgs e)
        {
            CloseCallback?.Invoke(this);
        }
        public Action<FrmImage> CloseCallback;
        /// <summary>
        /// 清除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmiClean_Click(object sender, EventArgs e)
        {
            Point screenPoint = Control.MousePosition;
            Point clientPoint = this.PointToClient(screenPoint);
            Control c = null;
            foreach (Control control in this.Controls)
            {
                if (new Rectangle(control.Location, control.Size).Contains(clientPoint))
                {
                    c = control;
                    break;
                }
            }
            if (c != null)
            {
                this.Controls.Remove(c);
            }
        }
        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmiClear_Click(object sender, EventArgs e)
        {
            List<Control> cs = new List<Control>(this.Controls.Count);
            foreach (Control control in this.Controls)
            {
                cs.Add(control);
            }
            foreach (Control c in cs)
            {
                this.Controls.Remove(c);
            }
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmiSave_Click(object sender, EventArgs e)
        {
            using SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Title = "保存文件";
            saveFileDialog.FileName = "example";
            saveFileDialog.DefaultExt = "png";
            saveFileDialog.Filter = "PNG 文件 (*.png)|*.png|JPEG 文件 (*.jpg)|*.jpg|BMP 文件 (*.bmp)|*.bmp|所有文件 (*.*)|*.*";
            if (saveFileDialog.ShowDialog() != DialogResult.OK) return;
            string filePath = saveFileDialog.FileName;
            using Bitmap map = new Bitmap(_fileImage);
            if (this.Controls.Count != 0)
            {
                using Graphics g = Graphics.FromImage(map);
                g.Smooth();
                foreach (Control control in this.Controls)
                {
                    int adjustedX = (int)(control.Location.X / _scaleX + (control.Width / _scaleX - control.Width / _scale));
                    int adjustedY = (int)(control.Location.Y / _scaleY - (control.Height / _scaleY - control.Height / _scale) / 2f - 40);
                    int adjustedWidth = (int)(control.Width / _scale);
                    int adjustedHeight = (int)(control.Height / _scale);
                    if (control is IDrawControl dc)
                    {
                        //g.DrawImage(dc.Image, adjustedX, adjustedY, adjustedWidth, adjustedHeight);

                        using Bitmap scaledImage = new Bitmap(adjustedWidth, adjustedHeight);
                        using Graphics scaledGraphics = Graphics.FromImage(scaledImage);
                        scaledGraphics.Smooth();
                        scaledGraphics.Clear(Color.Transparent);
                        scaledGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        scaledGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        scaledGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        scaledGraphics.DrawImage(dc.Image, new Rectangle(0, 0, adjustedWidth, adjustedHeight));

                        g.DrawImage(scaledImage, adjustedX, adjustedY);
                    }
                }
            }
            map.Save(filePath);
        }
    }
}
